package gs

import "log"

type GolangCode struct {
	Str
}

func (str Str) Golang() GolangCode {
	return GolangCode{str}
}

func EachPrint(pre string, color string) func(ix int, item Str) {
	return func(ix int, item Str) {
		item.Color(color).Println(pre)
	}
}

func EachDictPrint(pre string, color string) func(key string, item Str) {
	return func(key string, item Str) {
		item.Color(color).Println(pre, " key:", key)
	}
}

func (text GolangCode) CodeQuoteRandom() GolangCode {
	key := text.RandStr(8)
	// Str("before").Println()
	textconst, constCode := text.RemoveCommit().ExtractMark("const (", "\n)")
	// textconst.Println("code2")
	// text.RemoveCommit().Color("g").Println()
	// log.Fatal("")
	// constCode.Every(EachDictPrint("const", "g"))

	texts, lineImportCode := textconst.ExtractLine(func(lineno int, line Str) bool {
		if line.Trim().StartsWith("import \"") && line.Trim().EndsWith("\"") {
			return true
		}
		return false
	})
	// if lineImportCode.Len() > 0 {
	// 	textconst.MarkColor("import \"", "\"").Println("test import")
	// }

	textImport, importKeys := texts.ExtractMark("import (", "\n)")
	textImportSkipStruct, structCode := textImport.ExtractReMark(`type\s\w+\sstruct`, "\n}")
	textS, keys := textImportSkipStruct.QuoteMark()
	// textS.FormatDict(keys.With(func(k string, v Str) Str {
	// 	return v.Color("F", "B", "g")
	// })).Println("quoted")
	// textImportSkipStruct.Color("y").Println("code")
	// keys.Every(EachDictPrint("quote", "g"))
	randFuncName := text.RandStr(7)
	keyss := keys.With(func(k string, v Str) Str {
		if e, err := v.Unquote(); err != nil {
			// keys.Every(EachDictPrint("gg", "g"))
			// textImportSkipStruct.ToFile("../../test.go")
			textImportSkipStruct.QuotedStrsDebug()
			log.Fatal("err")
			return randFuncName + Str("(\"") + e + Str("\", \"") + key + Str("\",true)")
		} else {
			e = e.Enrypt(key.String())
			return randFuncName + Str("(\"") + e + Str("\", \"") + key + Str("\",true)")
		}

	})
	textN := textS.FormatDict(keyss)
	textN2 := textN.FormatDict(importKeys).FormatDict(lineImportCode)
	textN3 := textN2.FormatDict(structCode).FormatDict(constCode)
	return GolangCode{textN3}.codeAddEncrypt(randFuncName)
}

func (text GolangCode) CodeAddImport(importName string) GolangCode {
	if text.In("import (") && text.In("\n)") {

		nstr := text.TextChange("import (", "\n)", func(oldIn Str) (newIn Str) {
			if oldIn.In("\"" + importName + "\"") {
				return oldIn
			}
			return oldIn + "\n\t\"" + Str(importName) + "\""
		})
		return GolangCode{nstr}
	} else {
		nstr := text.TextEveryLineWith(func(lineno int, line Str) Str {
			if line.StartsWith("package ") {
				return line + "\nimport\t(\n\r\"" + Str(importName) + "\"\n)"
			} else {
				return line
			}
		})
		return GolangCode{nstr}

	}
}

func (text GolangCode) codeAddEncrypt(funcName Str) (newText GolangCode) {
	newTexts := text.CodeAddImport("encoding/hex").Str
	return GolangCode{Str(newTexts.String() + "\n" + `
	
func ` + funcName.String() + `(raws, k string, de ...bool) (ws string) {
	raw := []byte(raws)
	var e error
	key := []byte(k)

	if de != nil && de[0] {
		raw, e = hex.DecodeString(raws)
		if e != nil {
			return e.Error()
		}
	}
	w := make([]byte, len(raw))
	kl := len(key)
	for i, c := range raw {
		ci := key[i%kl]
		d := c ^ ci
		w[i] = d
	}
	if de != nil && de[0] {
		return string(w)
	}
	wsw := hex.EncodeToString(w)
	return wsw
}

`)}
}

func (text GolangCode) ToStr() Str {
	return text.Str
}
